﻿#region Header
// Copyright 2007-2011, Jerónimo Milea
// 
// This file is part of NetJsWire.
// 
//     NetJsWire is free software: you can redistribute it and/or modify
//     it under the terms of the GNU General Public License as published by
//     the Free Software Foundation, either version 3 of the License, or
//     (at your option) any later version.
// 
//     NetJsWire is distributed in the hope that it will be useful,
//     but WITHOUT ANY WARRANTY; without even the implied warranty of
//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//     GNU General Public License for more details.
// 
//     You should have received a copy of the GNU General Public License
//     along with NetJsWire.  If not, see <http://www.gnu.org/licenses/>.
#endregion
#region Using

using System;
using System.Collections.Generic;
using System.ComponentModel;
using NetJsWire.JsonRpcHandler;
using NetJsWire.Widgets.Data;
using Newtonsoft.Json;

#endregion

namespace NetJsWire.Widgets.Config
{
    [TypeConverter( typeof( ExpandableObjectConverter ) ), TypeDescriptionProvider( typeof( ConfigOptionsPropertys ) )]
    [Serializable]
    [JsonObject( MemberSerialization = MemberSerialization.OptIn )]
    public class StoreConfigOptions : ObservableConfigOptions
    {
        protected string _xtype = "store";

        /// <summary>
        ///   Default constructor
        /// </summary>
        /// <param name = "ownerWidget">The owner of this configuration</param>
        public StoreConfigOptions( IWidget ownerWidget )
            : base( ownerWidget )
        {
        }

        [Browsable( true ), DefaultValue( "store" )]
        [JsonProperty( "xtype", DefaultValueHandling = DefaultValueHandling.Include, NullValueHandling = NullValueHandling.Ignore, ObjectCreationHandling = ObjectCreationHandling.Reuse )]
        [TypeConverter( typeof( XtypeStringConverter ) )]
        public override string Xtype
        {
            get { return _xtype; }
            set
            {
                SetValue( "xtype", value, "store", _xtype );
                _xtype = value;
            }
        }

        #region Implementation of IConfigOptions

        private bool _autoSave = true;

        private List<BaseParam> _baseParams = new List<BaseParam>();

        private bool _batch = true;

        private ParamNames _defaultParamNames = new ParamNames();

        private ParamNames _paramNames = new ParamNames();

        private DataProxy _proxy;

        private bool _pruneModifiedRecords;

        private DataReader _reader;

        private bool _remoteSort;

        private bool _restFul;

        private SortInfo _sortInfo;

        private string _storeId;

        private string _url;

        private DataWriter _writer;

        [DefaultValue( true )]
        [Description( "Defaults to true causing the store to automatically save records to the server when a record is modified" )]
        [Browsable( true )]
        [JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, ObjectCreationHandling = ObjectCreationHandling.Reuse )]
        public override bool AutoSave
        {
            get { return _autoSave; }
            set
            {
                SetValue( "autoSave", value, true, _autoSave );
                _autoSave = value;
            }
        }

        [Description( "An object containing properties which are to be sent as parameters for every HTTP request." )]
        [DefaultValue( typeof( List<BaseParam> ) )]
        [Browsable( true )]
        [TypeConverter( typeof( CollectionConverter ) )]
        [DesignerSerializationVisibility( DesignerSerializationVisibility.Content )]
        [JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, ObjectCreationHandling = ObjectCreationHandling.Reuse )]
        public override List<BaseParam> BaseParams
        {
            get { return _baseParams; }
            set
            {
                SetValue( "baseParams", value, null, _baseParams );
                _baseParams = value;
            }
        }

        [DefaultValue( true )]
        [Description( "Defaults to true (unless restful==true). Multiple requests for each CRUD action (CREATE, READ, UPDATE and DESTROY) will be combined and sent as one transaction.\nOnly applies when autoSave is set to false." )]
        [Browsable( true )]
        [JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, ObjectCreationHandling = ObjectCreationHandling.Reuse )]
        public override bool Batch
        {
            get { return _batch; }
            set
            {
                SetValue( "batch", value, true, _batch );
                _batch = value;
            }
        }

        [Description( "Provides the default values for the paramNames property.\nTo globally modify the parameters for all stores, this object should be changed on the store prototype." )]
        [DefaultValue( ( string ) null )]
        [Browsable( true )]
        [TypeConverter( typeof( ExpandableObjectConverter ) )]
        [DesignerSerializationVisibility( DesignerSerializationVisibility.Content )]
        [JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, ObjectCreationHandling = ObjectCreationHandling.Reuse )]
        public override ParamNames DefaultParamNames
        {
            get { return _defaultParamNames; }
            set
            {
                SetValue( "defaultParamNames", value, null, _defaultParamNames );
                _defaultParamNames = value;
            }
        }

        [Description( "An object containing properties which specify the names of the paging and sorting parameters passed to remote servers when loading blocks of data." )]
        [DefaultValue( null )]
        [Browsable( true )]
        [TypeConverter( typeof( ExpandableObjectConverter ) )]
        [DesignerSerializationVisibility( DesignerSerializationVisibility.Content )]
        [JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, ObjectCreationHandling = ObjectCreationHandling.Reuse )]
        public override ParamNames ParamNames
        {
            get { return _paramNames; }
            set
            {
                SetValue( "paramNames", value, null, _paramNames );
                _paramNames = value;
            }
        }

        [Description( "The DataProxy object which provides access to a data object." )]
        [DefaultValue( null )]
        [Browsable( true )]
        [JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, ObjectCreationHandling = ObjectCreationHandling.Reuse )]
        [AttributeProvider( typeof( DataProxy ) )]
        public override DataProxy Proxy
        {
            get { return _proxy; }
            set
            {
                SetValue( "proxy", value, null, _proxy );
                _proxy = value;
            }
        }

        [Description( "true to clear all modified record information each time the store is loaded or when a record is removed (defaults to false)." )]
        [DefaultValue( false )]
        [Browsable( true )]
        [JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, ObjectCreationHandling = ObjectCreationHandling.Reuse )]
        public override bool PruneModifiedRecords
        {
            get { return _pruneModifiedRecords; }
            set
            {
                SetValue( "pruneModifiedRecords", value, false, _pruneModifiedRecords );
                _pruneModifiedRecords = value;
            }
        }

        [Description( "The Reader object which processes the data object and returns an Array of Ext.data.Record objects which are cached keyed by their id property." )]
        [DefaultValue( null )]
        [AttributeProvider( typeof( DataReader ) )]
        [Browsable( true )]
        [JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, ObjectCreationHandling = ObjectCreationHandling.Replace, IsReference = false )]
        public override DataReader Reader
        {
            get { return _reader; }
            set
            {
                SetValue( "reader", value, null, _reader );
                _reader = value;
            }
        }

        [Description( "true if sorting is to be handled by requesting the Proxy to provide a refreshed version of the data object in sorted order, as opposed to sorting the Record cache in place (defaults to false)." )]
        [DefaultValue( false )]
        [Browsable( true )]
        [JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, ObjectCreationHandling = ObjectCreationHandling.Reuse )]
        public override bool RemoteSort
        {
            get { return _remoteSort; }
            set
            {
                SetValue( "remoteSort", value, false, _remoteSort );
                _remoteSort = value;
            }
        }

        [Description( "Defaults to false. Set to true to have the Store and the set Proxy operate in a RESTful manner." )]
        [DefaultValue( false )]
        [Browsable( true )]
        [JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, ObjectCreationHandling = ObjectCreationHandling.Reuse )]
        public override bool RestFul
        {
            get { return _restFul; }
            set
            {
                SetValue( "restFul", value, false, _restFul );
                _restFul = value;
            }
        }

        [Description( "Defaults to false. Set to a config object to specify the sort order in the request of a Store's load operation. Note that for local sorting, the direction property is case-sensitive." )]
        //[DefaultValue( typeof( SortInfo ), "{SortProperty:null, Direction=SortDir.ASC}" )]
        [Browsable( true )]
        [TypeConverter( typeof( SortInfoConverter ) )]
        [DesignerSerializationVisibility( DesignerSerializationVisibility.Content )]
        [JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, ObjectCreationHandling = ObjectCreationHandling.Reuse )]
        public override SortInfo SortInfo
        {
            get { return ( _sortInfo ?? ( _sortInfo = new SortInfo() ) ); }
            set
            {
                SetValue( "sortInfo", value, null, _sortInfo );
                _sortInfo = value;
            }
        }

        [Description( "If passed, the id to use to register with the StoreMgr." )]
        [DefaultValue( ( string ) null )]
        [Browsable( true )]
        [JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, ObjectCreationHandling = ObjectCreationHandling.Reuse )]
        public override string StoreId
        {
            get { return _storeId; }
            set
            {
                SetValue( "storeId", value, null, _storeId );
                _storeId = value;
            }
        }

        [Description( "If a proxy is not specified the url will be used to implicitly configure a HttpProxy if an url is specified." )]
        [DefaultValue( ( string ) null )]
        [Browsable( true )]
        [JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, ObjectCreationHandling = ObjectCreationHandling.Reuse )]
        public override string Url
        {
            get { return _url; }
            set
            {
                SetValue( "url", value, null, _url );
                _url = value;
            }
        }

        [Description( "The Writer object which processes a record object for being written to the server-side database." )]
        [DefaultValue( null )]
        [Browsable( true )]
        [JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, ObjectCreationHandling = ObjectCreationHandling.Reuse )]
        [AttributeProvider( typeof( DataWriter ) )]
        public override DataWriter Writer
        {
            get { return _writer; }
            set
            {
                SetValue( "writer", value, null, _writer );
                _writer = value;
            }
        }

        #endregion

        public bool ShouldSerializeBaseParams()
        {
            return BaseParams != null && BaseParams.Count > 0;
        }

        public bool ShouldSerializeDefaultParamNames()
        {
            return DefaultParamNames != null && ( !string.IsNullOrEmpty( DefaultParamNames.Start ) || !string.IsNullOrEmpty( DefaultParamNames.Limit ) || !string.IsNullOrEmpty( DefaultParamNames.Dir ) || !string.IsNullOrEmpty( DefaultParamNames.Sort ) );
        }

        public bool ShouldSerializeParamNames()
        {
            return ParamNames != null && ( !string.IsNullOrEmpty( ParamNames.Start ) || !string.IsNullOrEmpty( ParamNames.Limit ) || !string.IsNullOrEmpty( ParamNames.Dir ) || !string.IsNullOrEmpty( ParamNames.Sort ) );
        }

        public virtual bool ShouldSerializeSortInfo()
        {
            return SortInfo != null && !string.IsNullOrWhiteSpace( SortInfo.SortProperty );
        }

        public void ResetSortInfo()
        {
            SortInfo.Direction = SortDir.ASC;
            SortInfo.SortProperty = null;
        }
    }
}